package com.ylz.sjzx.sio.sdk.client.session;

import com.ylz.sjzx.sio.common.core.constant.Const;
import com.ylz.sjzx.sio.common.mid.cache.redis.JedisTemplate;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;

/**
 * 用户信息进程缓存
 * 区别于imSession ImSession是每次连接都有一个新的session userSession是每个用户每个进程只有一份
 * UserSession可以理解为二级缓存
 * imSession可以理解为三级缓存
 *
 * @author
 * @version 1.0
 * @date 2021/2/23
 */
@Slf4j
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserSession implements Serializable {
    /**
     * 该用户每次连接的缓存 每次该用户重新连接都会被更新
     */
    private IMSession imSession;
    /**
     * 主键ID
     */
    private String userId;
    /**
     * 本地锁
     */
    private UserLock localUserLock = new LocalUserLock();
    /**
     * 本地锁
     */
    private UserLock distributedUserLock = new DistributedUserLock();

    public Boolean lockLogin() {
        return this.distributedUserLock.tryLock();
    }

    public void unLockLogin() {
        //判断目前处于什么锁 默认分布式
        this.distributedUserLock.unLock();
    }


    private abstract class UserLock {
        /**
         * 尝试加锁
         *
         * @return
         */
        abstract Boolean tryLock();

        /**
         * 解锁
         */
        abstract void unLock();
    }

    /**
     * 本地锁
     */
    private class LocalUserLock extends UserLock {
        /**
         * 锁
         */
        private volatile Boolean lock = false;

        private volatile Long lockTime = System.currentTimeMillis();

        @Override
        Boolean tryLock() {
            synchronized (this) {
                if (!lock) {
                    lock = true;
                    lockTime = (System.currentTimeMillis());
                    return true;
                }
                if (System.currentTimeMillis() - lockTime >= 400) {
                    log.info("=======旧锁超时,获取新锁============");
                    lock = true;
                    lockTime = (System.currentTimeMillis());
                    return true;
                }
                return false;
            }
        }

        @Override
        void unLock() {
            lock = false;
        }

    }

    /**
     * 分布所锁
     */
    private class DistributedUserLock extends UserLock {
        private String lock = "lock";

        @Override
        Boolean tryLock() {
            // 尝试获取锁 并且设置过期时间
            return JedisTemplate.me().setnx(Const.DISTRIBUTED_SESSION + userId + ":" + lock, lock, 400);
        }

        @Override
        void unLock() {
            JedisTemplate.me().delKey(Const.DISTRIBUTED_SESSION + userId + ":" + lock);
        }
    }
}
